package main;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Observable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.net.MalformedURLException;
import java.net.URL;

//TODO: handle javascript!!!! Example: http://css.insttech.washington.edu/~mealden/2/
//TODO: tighten logic for checking if link is absolute (buildLink())
public class PageParser extends Observable{
	//fields
	List<String> myWords;
	private int maxPages;
	private int pageCount;
	
	//create PageParser
	public PageParser() {
		myWords = new ArrayList<String>();
		maxPages = 0;
		pageCount = 0;
	}
	
	public void setUp(final int numPages) {
		maxPages = numPages;
	}
	
	/**
	 * Parses page from fetched URL.
	 * Generates a collection of URLs the page links to as well as a collection of words found in the body text of the parsed page.
	 * @param theAbsolutePath	The absolute path to the parsed page
	 * @param thePageContents	The contents of the page to be parsed 
	 * @throws MalformedURLException
	 */
	public void parsePage(Page thePage) throws MalformedURLException {
		System.out.println("parsing '" + thePage.getURL().toString() + "'.......................................................");
		List<URL> urlList = new ArrayList<URL>(); //for now - will add to the collection the controller handles later
		List<String> words = new ArrayList<String>();
		int numLinks = 0;
		
        // timer variables
        long parseTime = 0;
		long startTime = 0;
        long finishTime = 0;
        // start the timer
        Date startDate = new Date();
        startTime = startDate.getTime();
        
		Document doc = Jsoup.parse(thePage.getContents());
		
		Elements links = doc.select("a[href]");

		//build collection of "valid" links
        for (Element link : links) { //build links and add them to the collection of links found in this page
        	String strLink = buildLink(thePage.getURL(), link.attr("href"));
        	if (strLink != null) { //validation happens in the PageRetriever
        		urlList.add(new URL(strLink));
        		numLinks++;
        	}
        }

        //rough tokenization - may need optimizing
        //build collection of words
        String[] titleText = doc.title().split("\\s+");
        for (String word : titleText) {
        	if (word.endsWith(",") || word.endsWith(".") || word.endsWith(";")) {
        		word = word.substring(0, word.length()-1);
        	}
        	words.add(word);
        }
        String[] bodyText = doc.body().text().split("\\s+");
        for (String word : bodyText) {
        	while (word.endsWith(",") || word.endsWith(".") || word.endsWith(";")) {
        		word = word.substring(0, word.length()-1).trim();
        	}
        	words.add(word);
        }
        thePage.setLinks(urlList);
        thePage.setWords(words);
        
        // stop the timer
        Date finishDate = new Date();
        finishTime = finishDate.getTime();
        parseTime += (finishTime - startTime)/1000; //milliseconds to seconds
        
        thePage.setParseTime(parseTime);
        
        System.out.println("completed parsing.");
		this.setChanged();
		this.notifyObservers(thePage);
	}
	
	/**
	 * Checks to see if link is absolute or relative.
	 * Builds link from absolute path concatenated with relative link found in body of page.
	 * If link is absolute, returns link
	 * @param theAbsolutePath	The URL of the page that contains the link
	 * @param theLink			The link found in the page being parsed
	 * @return String			The absolute path to the linked page
	 */
	public String buildLink(final String theAbsolutePath, final String theLink) {
		//so far, this works with alden's website, but will have to test other websites....
		System.out.println("Building link with '" + theAbsolutePath + "' and '" + theLink + "'");
		String pathToLink = new String();

		if (theLink.startsWith("#")) {
			pathToLink = null;
		} else if (theLink.startsWith("http:") || theLink.startsWith("www.")) { //link is absolute; return link itself
			//TODO: this can't be all of them...
			pathToLink = theLink;
		} else if (!theAbsolutePath.endsWith("/")){ //need to cut off the end and cat it to link
			pathToLink = theAbsolutePath.substring(0, theAbsolutePath.lastIndexOf("/") + 1) + theLink;
		} else { //concatenate absolute and relative
			pathToLink = theAbsolutePath + theLink;
		}
		System.out.println("PP added link: " + pathToLink);
		return pathToLink;
	}
}
